#include "Sock.hpp"
#include "log.hpp"
#include <string>
#include <pthread.h>
#include <functional>
using func_t = std::function<std::string(std::string)>;
class Httpserver;
class ThreadData
{
public:
    ThreadData(std::string ip, uint16_t port, int socket, Httpserver*hs)
        : ip_(ip)
        , port_(port)
        , socket_(socket)
        ,hs_(hs)
    {
        ;
    }
    std::string ip_;
    uint16_t port_;
    int socket_;
    Httpserver *hs_;
};
class Httpserver
{
public:
    Httpserver(func_t func, int port)
        : func_(func), port_(port)
    {
        ;
    }
    void Init()
    {
        sock_.Socket();
        sock_.Bind(port_);
        sock_.Listen();
        log_(ErrorLevel::Debug, "Init success socket: %d", sock_.socket_);
    }
    void HandlerRequest(int socket)
    {
        // 1 读取数据
        while(true)
        {
            char buffer[10098] = {0};
            int n = recv(socket, buffer, sizeof(buffer) - 1, 0);
            if (n > 0)
            {
                // cout<<"n: "<<n<<endl;
                std::string Response = func_(buffer);
                send(socket,Response.c_str(),Response.size(),0);
            }
            else
            {
                // cout<<"n: "<<n<<endl;
                log_(ErrorLevel::Debug, "Quit...");
                sleep(1);
            }
        }
        
    }
    static void *threadRoutine(void *arg)
    {
        ThreadData *td = static_cast<ThreadData *>(arg);
        td->hs_->HandlerRequest(td->socket_);
        td->hs_->log_(ErrorLevel::Debug, "Quit...");

        close(td->socket_);
        delete td;
        return nullptr;
    }
    void start()
    {
        while(true)
        {
            std::string clientip;
            uint16_t port;
            int socket = sock_.Accept(&clientip, &port);
            if(socket < 0)
            {
                cout<<"continue "<<endl;
                continue;
            }
            log_(ErrorLevel::Debug, "Acccept success socket: %d",socket);
            pthread_t id;
            ThreadData *td = new ThreadData(clientip, port, socket,this);
            pthread_create(&id, nullptr, threadRoutine, td);
        }
    }
    ~Httpserver()
    {
        ;
    }
    Log log_;
    func_t func_;
    int port_;
    Sock sock_;
};
